package com.hansen.library.ui.widget.image;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;

import com.hansen.library.R;
import com.hansen.library.utils.ScreenSizeUtils;

/**
 * Created by han on 2019/2/18 0018.
 */

public class RatioRoundImageView extends AppCompatImageView {
    private final int TYPE_RATIO_BASE_WITH = 0;
    private final int TYPE_RATIO_BASE_HEIGHT = 1;
    private final float DefaultRatio = 0.0f;
    //圆角大小，默认为30
    private int mBorderRadius;
    // 3x3 矩阵，主要用于缩小放大
    private Matrix mMatrix;
    //渲染图像，使用图像为绘制图形着色
    private BitmapShader mBitmapShader;

    private RectF mBorderRect;

    private float ratio;
    private float scaleSize = 1;

    private boolean hasRoundTopLeft;
    private boolean hasRoundTopRight;
    private boolean hasRoundBottomLeft;
    private boolean hasRoundBottomRight;
    private boolean hasRoundAll;

    private int mWidth;
    private int mHeight;

    //0-以宽度为基础，0-以高度为基础
    private int mImageRatioType;

    private int mBorderWidth;
    private int mBorderColor;

    private Paint mPaint;
    private Paint mBorderPaint;

    public RatioRoundImageView(Context context) {
        this(context, null);
    }

    public RatioRoundImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RatioRoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RatioImageViewStyleable, defStyleAttr, 0);

        ratio = a.getFloat(R.styleable.RatioImageViewStyleable_image_ratio_attr, DefaultRatio);
        scaleSize = a.getFloat(R.styleable.RatioImageViewStyleable_image_round_press_scale, 1);

        mBorderRadius = a.getDimensionPixelOffset(R.styleable.RatioImageViewStyleable_image_round_radius, ScreenSizeUtils.dp2px(context, 5));

        hasRoundAll = a.getBoolean(R.styleable.RatioImageViewStyleable_image_round_all, false);
        hasRoundTopLeft = a.getBoolean(R.styleable.RatioImageViewStyleable_image_round_top_left, false);
        hasRoundTopRight = a.getBoolean(R.styleable.RatioImageViewStyleable_image_round_top_right, false);
        hasRoundBottomLeft = a.getBoolean(R.styleable.RatioImageViewStyleable_image_round_bottom_left, false);
        hasRoundBottomRight = a.getBoolean(R.styleable.RatioImageViewStyleable_image_round_bottom_right, false);

        mImageRatioType = a.getInt(R.styleable.RatioImageViewStyleable_image_ratio_type, TYPE_RATIO_BASE_WITH);

        mBorderWidth = a.getDimensionPixelOffset(R.styleable.RatioImageViewStyleable_image_round_border_width, 0);
        mBorderColor = a.getColor(R.styleable.RatioImageViewStyleable_image_round_border_color, Color.WHITE);

        a.recycle();

        if(hasRoundAll == true) {
            hasRoundTopLeft = hasRoundTopRight = hasRoundBottomLeft = hasRoundBottomRight = true;
        }

        if (hasRoundTopLeft || hasRoundTopRight || hasRoundBottomLeft || hasRoundBottomRight) {
            mPaint = new Paint();
            mMatrix = new Matrix();

            mPaint.setAntiAlias(true);
        }

        if(mBorderWidth > 0) {
            mBorderRect = new RectF();
            mBorderPaint = new Paint();

            mBorderPaint.setStyle(Paint.Style.STROKE);
            mBorderPaint.setColor(mBorderColor);
            mBorderPaint.setStrokeWidth(mBorderWidth);
            mBorderPaint.setAntiAlias(true);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if (ratio > 0.0f) {
            if (mImageRatioType == TYPE_RATIO_BASE_WITH) {
                int width = MeasureSpec.getSize(widthMeasureSpec);
                if (getTop() < 0) {//高度超出父组件高度时，重设比例
                    setMeasuredDimension(width, width);
                } else {
                    setMeasuredDimension(width, (int) (ratio * width));
                }
            } else {
                int height = MeasureSpec.getSize(heightMeasureSpec);
                setMeasuredDimension((int) (ratio * height), height);
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (hasRoundTopLeft || hasRoundTopRight || hasRoundBottomLeft || hasRoundBottomRight) {
            if (getDrawable() == null) {
                return;
            }
            Bitmap bitmap = drawableToBitamp(getDrawable());
            mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

            //设置centerCrop
            float scale;
            float dx = 0, dy = 0;
            int dwidth = bitmap.getWidth() - getPaddingLeft() - getPaddingRight();
            int dheight = bitmap.getHeight() - getPaddingTop() - getPaddingBottom();
            int vwidth = getWidth();
            int vheight = getHeight();

            if (dwidth * vheight > vwidth * dheight) {
                scale = (float) vheight / (float) dheight;
                dx = (vwidth - dwidth * scale) * 0.5f;
            } else {
                scale = (float) vwidth / (float) dwidth;
                dy = (vheight - dheight * scale) * 0.5f;
            }

            mMatrix.setScale(scale, scale);
            mMatrix.postTranslate(Math.round(dx), Math.round(dy));
            // 设置变换矩阵
            mBitmapShader.setLocalMatrix(mMatrix);
            // 设置shader
            mPaint.setShader(mBitmapShader);

            RectF rectF = new RectF(0, 0, getWidth(), getHeight());

            canvas.drawRoundRect(rectF, mBorderRadius, mBorderRadius,
                    mPaint);

            //哪个角不是圆角我再把你用矩形画出来,有描边无需画图片的直角，无描边再画图片直角
            if (!hasRoundTopLeft) {
                canvas.drawRect(rectF.left, rectF.top, rectF.left + mBorderRadius, rectF.top + mBorderRadius, mPaint);
            }
            if (!hasRoundTopRight) {
                canvas.drawRect(rectF.right - mBorderRadius, rectF.top, rectF.right, rectF.top + mBorderRadius, mPaint);
            }
            if (!hasRoundBottomLeft) {
                canvas.drawRect(rectF.left, rectF.bottom - mBorderRadius, rectF.left + mBorderRadius, rectF.bottom, mPaint);
            }
            if (!hasRoundBottomRight) {
                canvas.drawRect(rectF.right - mBorderRadius, rectF.bottom - mBorderRadius, rectF.right, rectF.bottom, mPaint);
            }
        } else {
            super.onDraw(canvas);
        }

        if (mBorderWidth > 0) {
            int divBorderWidth = mBorderWidth / 2;
            mBorderRect.set(divBorderWidth, divBorderWidth, getWidth() - divBorderWidth, getHeight() - divBorderWidth);
            canvas.drawRoundRect(mBorderRect, mBorderRadius, mBorderRadius, mBorderPaint);
        }
    }

    @Override
    public void setPressed(boolean pressed) {
        super.setPressed(pressed);
        if(scaleSize > 0 && scaleSize < 1) {
            if (isPressed()) {
                setScaleX(this.scaleSize);
                setScaleY(this.scaleSize);
            } else {
                setScaleX(1.0f);
                setScaleY(1.0f);
            }
        }
    }

    private Bitmap drawableToBitamp(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bd = (BitmapDrawable) drawable;
            return bd.getBitmap();
        }
        // 当设置不为图片，为颜色时，获取的drawable宽高会有问题，所有当为颜色时候获取控件的宽高
        int w = drawable.getIntrinsicWidth() <= 0 ? getWidth() : drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight() <= 0 ? getHeight() : drawable.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);
        return bitmap;
    }

    public void setBorderRadius(int mBorderRadius) {
        this.mBorderRadius = mBorderRadius;
    }

    public void setRatio(float ratio) {
        this.ratio = ratio;
    }

    public void setHasRoundAll(boolean hasRoundAll) {
        this.hasRoundAll = hasRoundAll;
        if(hasRoundAll) {
            if(mMatrix == null) mMatrix = new Matrix();
            if(mPaint == null) {
                mPaint = new Paint();
                mPaint.setAntiAlias(true);
            }
            hasRoundTopLeft = hasRoundTopRight = hasRoundBottomLeft = hasRoundBottomRight = true;
        }
    }
}
